%{
#include <stdio.h>
//#include <symbolTable.h>
//#define YYSTYPE char const *
int yylex(void);


%}
%union {
	char *stringValue;
	int intValue;
	float floatValue;
}

%type <stringValue> repeticao_identificador
%type <stringValue> nome_programa
%type <stringValue> declaracao_de_variavel
%type <stringValue> vazio
%type <stringValue> variavel
%type <stringValue> instrucao_de_atribuicao
%type <stringValue> expressao
%type <stringValue> expressao_simples
%type <stringValue> expressao_simples_fim
%type <stringValue> termo
%type <stringValue> fator

%token T_PROGRAMA
%token T_FUNCAO
%token T_PROCEDIMENTO
%token T_INTEIRO
%token T_TEXTO
%token T_INICIO
%token T_FIM
%token <stringValue> T_IDENTIFICADOR
%token T_VAR
%token T_TIPO
%token T_PACKED
%token T_PARENTESES_A
%token T_PARENTESES_F
%token T_VIRGULA
%token T_INTEIRO_SEM_SINAL 
%token T_REAL_SEM_SINAL
%token T_CONSTANTE
%token <stringValue> T_SINAL
%token T_PONTO
%token T_PONTO_VIRGULA
%token T_PARA
%token T_INCREMENTA
%token T_DECREMENTA
%token T_ENQUANTO
%token T_FACA
%token T_REPITA
%token T_ATE
%token T_DOIS_PONTOS
%token T_REGISTRO
%token T_DE
%token T_SE
%token T_ENTAO
%token T_SENAO
%token T_ATRIBUIR
%token T_ARQUIVO
%token T_COLCHETE_A
%token T_COLCHETE_F
%token T_MATRIZ
%token <stringValue> T_OP_ATRIBUICAO
%token T_OP_MAIOR
%token T_OP_MENOR
%token T_OP_MAIORIGUAL
%token T_OP_MENORIGUAL
%token T_OP_IGUAL
%token T_OP_DIFERENTE
%token T_OP_DIVISAO
%token T_OP_MULTIPLICACAO
%left T_OP_SUBTRACAO
%left T_OP_E
%left T_OP_OU
%left T_OP_NAO
%left T_OP_DIV
%left T_OP_MOD
%left T_OP_ADICAO

%start programa
%%
/* ###################################### INICIO ####################################### */

vazio:
	;
	
programa:
	cabecalho_programa T_PONTO_VIRGULA bloco_programa
	;
	
cabecalho_programa:
	T_PROGRAMA nome_programa T_PARENTESES_A parametro repeticao_parametro T_PARENTESES_F
	;
	
nome_programa:
	T_IDENTIFICADOR {printf("\n%s", $1);}
	;

parametro:
	vazio | T_IDENTIFICADOR
	;

repeticao_parametro:
	vazio | T_VIRGULA parametro repeticao_parametro
	;

bloco_programa:
	bloco
	;

bloco:
	{printf("\nregra esperada constantes ");}
	parte_definicao_constantes
	{printf("\nregra esperada tipos ");}
	parte_definicao_tipos
	{printf("\nregra esperada variaveis ");}
	parte_definicao_variaveis
	{printf("\nregra esperada funcoes e proc ");}
	parte_declaracao_funcao_procedimento
	{printf("\nregra esperada inicio ");}
	parte_instrucoes
	T_PONTO
	;

/* ####################################### CONSTANTES ################################### */

parte_definicao_constantes:
	vazio | T_CONSTANTE definicao_constante repeticao_definicao_constante
	;
	
definicao_constante:
	identificador_constante T_OP_IGUAL constante
	;
     
repeticao_definicao_constante:
	T_PONTO_VIRGULA definicao_constante repeticao_definicao_constante
	| T_PONTO_VIRGULA
	;
	

constante:
	numero_sem_sinal
	| T_SINAL numero_sem_sinal
	| identificador_constante
	| T_SINAL identificador_constante
	| T_TEXTO
	;

numero_sem_sinal:
	T_INTEIRO_SEM_SINAL | T_REAL_SEM_SINAL
	;

identificador_constante:
	T_IDENTIFICADOR
	;
/* ######################################### TIPOS ###################################### */

parte_definicao_tipos:
	 T_TIPO definicao_de_tipo repeticao_definicao_de_tipo {printf("k-entrou cheio");}
	 | vazio {printf("k-entrou vazio");}
	;
	
definicao_de_tipo:
	T_IDENTIFICADOR T_OP_IGUAL tipo
	;
	
repeticao_definicao_de_tipo:
	T_PONTO_VIRGULA definicao_de_tipo repeticao_definicao_de_tipo
	| T_PONTO_VIRGULA
	;
	
tipo: 
	tipo_simples | tipo_estruturado
	;
	
tipo_simples:
	tipo_escalar | tipo_identificador /* | tipo_sub_intervalo */
	;
	
tipo_escalar:
	T_IDENTIFICADOR repeticao_identificador
	;

repeticao_identificador:
	T_VIRGULA T_IDENTIFICADOR repeticao_identificador {strcpy($$, $2);}
	| vazio	{}
	;

tipo_identificador:
	T_IDENTIFICADOR
	;

tipo_estruturado:
	tipo_estruturado_descompactado
	| T_PACKED tipo_estruturado_descompactado
	;
	
tipo_estruturado_descompactado:	
	tipo_matriz 
	| tipo_registro 
	| tipo_arquivo
	/* | tipo_conjunto */
	;

tipo_matriz:
	T_MATRIZ T_COLCHETE_A tipo_indice repeticao_tipo_indice T_COLCHETE_F T_DE tipo_componente
	;

tipo_indice:
	tipo_simples
	| T_INTEIRO_SEM_SINAL
	;
	
repeticao_tipo_indice:
	T_VIRGULA tipo_indice repeticao_tipo_indice
	| vazio
	;

tipo_componente:
	tipo
	;
	
tipo_registro: 
	T_REGISTRO lista_de_campos T_FIM
	;

lista_de_campos:
	parte_fixa /* NAO USAREMOS:| parte_fixa T_PONTO_VIRGULA parte_variavel | parte_variavel*/
	;

parte_fixa:
	secao_de_registro repeticao_secao_de_registro
	;
	
secao_de_registro:
	identificador_campo repeticao_id_campo T_DOIS_PONTOS tipo
	| vazio
	;

repeticao_secao_de_registro:
	T_PONTO_VIRGULA secao_de_registro repeticao_secao_de_registro
	| T_PONTO_VIRGULA
	;

repeticao_id_campo:
	T_VIRGULA identificador_campo repeticao_id_campo
	| vazio
	;

identificador_campo:
	T_IDENTIFICADOR
	;

tipo_arquivo:
	T_ARQUIVO tipo
	;
/*	set of (consertar regra <tipo estruturado descompactado>)
atribuir_tipo:
	T_ATRIBUIR tipo_basico
	;
*/
tipo_basico:
	tipo_simples
	;
	
tipo_resultado:
	tipo_identificador
	;
/*	
vetor: T_IDENTIFICADOR T_DOIS_PONTOS T_VETOR  T_DE tipo
	;
*/	
/* ####################################### VARIAVEIS #################################### */	

parte_definicao_variaveis:
	T_VAR declaracao_de_variavel repeticao_declaracao_de_variavel
	| vazio
	;
	
declaracao_de_variavel:
	T_IDENTIFICADOR repeticao_identificador T_DOIS_PONTOS tipo {
		/*symbolTable new = createItem();
		new->name = $1;
		new->tipo = $4;
		new->classe = VARIAVEL;
		add(table, new);
		*/
		printf("id: (%s)\n", $1);
		printf("id: (%s)\n", $2);
		}
		
	;
	
repeticao_declaracao_de_variavel:
	T_PONTO_VIRGULA declaracao_de_variavel repeticao_declaracao_de_variavel
	| T_PONTO_VIRGULA
	;

variavel:
	T_IDENTIFICADOR {strcpy($$, $1);}
	| variavel_componente
	;
	
	/* buffer_de_arquivo momentaneamente retirado pois nao esta sendo
	 * tratado ponteiros. Esta gerando ambiguidade.
	 * */
variavel_componente:
	variavel_indexada 
	| designador_campo 
	/*| buffer_de_arquivo*/
	;
	
variavel_indexada:
	variavel_matriz T_COLCHETE_A expressao repeticao_expressao T_COLCHETE_F
	;
	
variavel_matriz:
	variavel
	;
	
designador_campo:
	variavel_registro T_PONTO identificador_campo
	;
	
variavel_registro:
	variavel
	;
/*	
buffer_de_arquivo:
	variavel
	;
*/
/* ##################################### PROCEDIMENTOS ################################## */	

parte_declaracao_funcao_procedimento:
	declaracao_funcao_procedimento T_PONTO_VIRGULA parte_declaracao_funcao_procedimento
	| vazio
	;
	
declaracao_funcao_procedimento:
	declaracao_procedimento
	| declaracao_funcao
	;

declaracao_procedimento:
	cabecalho_procedimento bloco
	;

cabecalho_procedimento:
	T_PROCEDIMENTO T_IDENTIFICADOR fim_cabecalho_procedimento
	;

fim_cabecalho_procedimento:
	T_PONTO_VIRGULA
	| T_PARENTESES_A parametro_formal repeticao_parametro_formal T_PARENTESES_F T_PONTO_VIRGULA
	;

parametro_formal:
	grupo_parametro 
	| T_VAR grupo_parametro
	| T_FUNCAO grupo_parametro
	| T_PROCEDIMENTO  T_IDENTIFICADOR repeticao_identificador
	;

repeticao_parametro_formal:
	T_DOIS_PONTOS parametro_formal repeticao_parametro_formal
	| vazio
	;

grupo_parametro:
	T_IDENTIFICADOR repeticao_identificador T_DOIS_PONTOS tipo_identificador
	;

/* ######################################## FUNCOES ##################################### */	

declaracao_funcao:
	cabecalho_funcao bloco
	;

cabecalho_funcao:
	T_FUNCAO T_IDENTIFICADOR fim_cabecalho_funcao
	;

fim_cabecalho_funcao:
	T_DOIS_PONTOS tipo_resultado T_PONTO_VIRGULA
	| T_PARENTESES_A parametro_formal repeticao_parametro_formal T_PARENTESES_F T_DOIS_PONTOS tipo_resultado T_DOIS_PONTOS 
	;

designador_funcao:
	identificador_funcao
	| identificador_funcao T_PARENTESES_A parametro repeticao_parametro T_PARENTESES_F
	;

identificador_funcao:
	T_IDENTIFICADOR
	;
	
/* ###################################### INSTRUCOES #################################### */	
	
parte_instrucoes:
	instrucao_composta
	;

/* Adicao do terminal T_PONTO_VIRGULA na regra instrucao_composta*/
instrucao_composta:
	T_INICIO instrucao repeticao_instrucao T_FIM
	;
	
repeticao_instrucao:
	T_PONTO_VIRGULA instrucao repeticao_instrucao
	| vazio
	;
	
instrucao:
	instrucao_simples {printf("\nsimples");}
	| instrucao_estruturada {printf("\nestruturada");}
	;
	
instrucao_simples:
	instrucao_de_atribuicao
	| instrucao_procedimento
	| vazio
	;

instrucao_de_atribuicao:
	variavel T_OP_ATRIBUICAO expressao {printf("\n(%s) (%s) (%s)\n", $1, $2, $3);}
	| identificador_funcao T_OP_ATRIBUICAO expressao
	;

instrucao_procedimento:
	identificador_procedimento
	| identificador_procedimento T_PARENTESES_A parametro repeticao_parametro T_PARENTESES_F
	;

identificador_procedimento:
	T_IDENTIFICADOR
	;

expressao:
	expressao_simples {strcpy($$, $1);}
	| expressao_simples operador_relacional expressao_simples {printf("\nexpressao relacional");}
	;
repeticao_expressao:
	T_VIRGULA expressao repeticao_expressao
	| vazio
	; 
	
operador_relacional:
	T_OP_IGUAL 
	| T_OP_DIFERENTE 
	| T_OP_MENOR 
	| T_OP_MENORIGUAL 
	| T_OP_MAIORIGUAL 
	| T_OP_MAIOR
	;

expressao_simples:
	expressao_simples_fim {strcpy($$, $1);}
	| T_SINAL  expressao_simples_fim {printf("sinal: %s\n", $1);}
	;

expressao_simples_fim:
	termo	{strcpy($$, $1);}
	| termo operador_adicional expressao_simples_fim
	;
	
termo:
	fator {strcpy($$, $1);}
	| fator operador_multiplicador termo
	;

operador_multiplicador:
	T_OP_DIVISAO 
	| T_OP_E 
	| T_OP_MOD 
	| T_OP_DIV 
	| T_OP_MULTIPLICACAO
	;

fator:
	variavel {strcpy($$, $1);}
	| T_PARENTESES_A expressao T_PARENTESES_F
	| T_OP_NAO fator
	| designador_funcao
	| numero_sem_sinal {printf("\nfator num");}
	;

operador_adicional:
	T_OP_ADICAO 
	| T_OP_SUBTRACAO 
	| T_OP_OU
	;

instrucao_estruturada:
	instrucao_condicional 
	| instrucao_repeticao {printf("\ninstrucao rfepeticao");}
	| instrucao_composta
	;

instrucao_condicional:
	instrucao_se
	;

instrucao_se:
	T_SE expressao T_ENTAO instrucao
	| T_SE expressao T_ENTAO instrucao T_SENAO instrucao
	;

instrucao_repeticao:
	instrucao_enquanto {printf("\nreconheceu expressao");}
	| instrucao_repita 
	| instrucao_para
	;
	
instrucao_enquanto:
	T_ENQUANTO expressao T_FACA instrucao
	;

instrucao_repita:
	T_REPITA instrucao T_ATE expressao
	;
	
instrucao_para:
	T_PARA T_IDENTIFICADOR  T_OP_ATRIBUICAO expressao T_INCREMENTA T_ATE expressao T_FACA instrucao
	| T_PARA T_IDENTIFICADOR  T_OP_ATRIBUICAO expressao T_DECREMENTA T_ATE expressao T_FACA instrucao
	;
	
/* ###################################### OUTROS #################################### */
	



/* ###################################### FIM #################################### */

%%

int yyerror(char *s) {
        printf("\nyyerror %s\n", s);
}

int mainParser() {
        yyparse();
}
